<template>
	<view style="width: 100%;height: 100vh;position: relative;overflow: hidden;">
		<image src="../static/background2.jpg" style="height: 100vh;width: 100%;position: absolute;left: 0%;top: 0%;">
		</image>
		<view class='container bg-gray'>
			<tn-nav-bar bgClass="bg-gradual-blue2">
				<view>
					{{ bleName }}
				</view>
			</tn-nav-bar>
			<view :style="{paddingTop: vuex_custom_bar_height + 'px'}">
				<view class="flex align-center padding-right-xs justify-end">
					<image src="/static/img/ble/ble_logo.png" style="width: 25px;height: 25px;">
					</image>
					<text class="padding-left-sm text-bold text-xl margin-right" style="color: #0081ff;">已连接</text>
					<text class="padding-left-sm text-bold text-xl margin-right" style="color: #eb1f0c;">未连接</text>
				</view>
				<view class="padding-sm padding-bottom-xs flex justify-between">
					<view class="flex">
						<acqui-dynamic-message :messageList="PackInfo['Protect'].tValue"
							ref="dynamicMessage"></acqui-dynamic-message>
					</view>
					
					<view class="flex align-center">
						<text class="margin-right cuIcon-clothes tn-text-xxl" style="color: #0081ff;" @click="setImg" />
					</view>

				</view>


				<view class="margin-sm tn-flex tn-flex-row-center"
					style="align-items: center;flex-direction: column;margin-bottom: 0;">
					<view style="justify-content: center;">
						<image class="tn-flex-row-center" :src="carImgs[imgNum]" style="width: 240px;height: 168px;"
							@click="showPasswordFun('CONFIG')"></image>
					</view>
					<view class="tn-margin"
						style="height: 325px;width: 100%;margin-top: -80px;border-radius: 30rpx; background-color: rgb(255 255 255 / 70%);">
						<view class="tn-flex" style="margin-top: 80px;width: 100%;height: 140px;">
							<view class="tn-flex-basic-md tn-margin b-card tn-margin-right-xs">
								<view
									class="tn-flex tn-flex-row-between tn-flex-col-bottom tn-text-bold text-xxl text-black tn-margin-sm">
									<text class="">{{PackInfo['SOC'].tValue?PackInfo['SOC'].tValue: 0}} %</text>
									<text class="text-gray text-lg" style="letter-spacing: 1px">剩余电量</text>
								</view>
								<zuBattery :battery="PackInfo['SOC'].tValue" height='80rpx' width="260rpx">
								</zuBattery>
							</view>
							<view class="tn-flex-basic-md tn-margin tn-margin-left-sm b-card text-black text-bold ">
								<view class="tn-flex tn-flex-direction-column ">
									<view class="tn-flex  tn-flex-row-center tn-flex-col-center"
										style="height: 105rpx;">
										<text class="tn-icon-light-fill text-lg padding-xs"> </text>
										<text class="padding-right text-bold text-xl" style="letter-spacing: 2px">
											充电</text>
										<switch class="radius" @change='e=>mosBtnComfig(e,"01")'
											:class="PackInfo['MosCtrl'].tValue[0]?(PackInfo['MosCtrl'].tValue[0]*1>0?'checked':''):''"
											:checked="PackInfo['MosCtrl'].tValue[0]?(PackInfo['MosCtrl'].tValue[0]*1>0?true:false):false">
										</switch>
									</view>
									<view class="tn-flex  tn-flex-row-center tn-flex-col-center"
										style="height: 105rpx;">
										<text class="tn-icon-logout text-lg padding-xs"></text>
										<text class="padding-right text-bold text-xl" style="letter-spacing: 2px">
											放电</text>
										<switch class="radius" @change='e=>mosBtnComfig(e,"00")'
											:class="PackInfo['MosCtrl'].tValue[1]?(PackInfo['MosCtrl'].tValue[1]*1>0?'checked':''):''"
											:checked="PackInfo['MosCtrl'].tValue[1]?(PackInfo['MosCtrl'].tValue[1]*1>0?true:false):false">
										</switch>
									</view>
								</view>
							</view>

						</view>
						<view class="margin-lr margin-bottom b-card">
							<view class="grid col-3 flex justify-center padding-tb">
								<view class="flex flex-direction align-center justify-center">
									<view class="text-blue2 text-bold text-xxl">
										{{ PackInfo.Voltage.tValue?PackInfo.Voltage.tValue:0 }} V
									</view>
									<view>电池电压</view>
								</view>
								<view class="flex flex-direction align-center justify-center">
									<view class="text-blue2 text-bold text-xxl">
										{{ PackInfo.CurCadc.tValue?PackInfo.CurCadc.tValue: '0.0' }} A
									</view>
									<view>当前电流</view>
								</view>
								<view class="flex flex-direction align-center justify-center">
									<view class="text-blue2  text-bold text-xxl">
										{{PowerW?PowerW: '0.0'}} W
									</view>
									<view>运行功率</view>
								</view>
							</view>
							<!-- <view class="grid col-2 flex justify-center padding-tb">
								
								<view class="flex flex-direction align-center justify-center">
									<view class="text-blue2  text-bold text-xxl">
										{{VCellInfo.vMax?(VCellInfo.vMax - VCellInfo.vMin): 0}} mV
									</view>
									<view>最大压差</view>
								</view>
								<view class="flex flex-direction align-center justify-center">

								</view>
							</view> -->
						</view>
					</view>
				</view>


				<view class="margin-sm radius-25" style="margin-top: 0;box-shadow: 2rpx 2rpx 4rpx 4rpx #def4f9;">
					<tn-collapse arrowColor='#0081ff'>
						<tn-collapse-item ref='collapse_1' icon='tn-icon-temperature-c' title="温度"
							subTitle='temperature'>
							<view class="cu-card tn-flex tn-flex-basic-sm tn-flex-direction-row">
								<view class="tn-flex justify-center align-center">
									<image src="/static/img/ble/wd.png" style="width: 128px;max-height: 128px;"
										mode="" />
								</view>
								<view class="tn-flex tn-flex-basic-lg tn-flex-direction-column">
									<view
										class="tn-flex margin-lr-sm padding-tb  shadow solid-bottom  justify-around tn-flex-direction-row">
										<view>
											<text class="text-bold">MOS</text>
											<text class="padding-left-xs text-bold text-blue2">
												{{PackInfo.TempNum.tValue?PackInfo.Temp.tValue[0]: '0.0'}} ℃
											</text>
										</view>
										<view>
											<text class="text-bold">湿度</text>
											<text class="padding-left-xs text-bold text-blue2">
												{{PackInfo.ShiDu.tValue?PackInfo.ShiDu.tValue: '0'}} %
											</text>
										</view>
									</view>
									<view class="grid col-2">
										<view style="display: flex; justify-content: center;"
											v-for="(item ,index) in PackInfo.TempNum.tValue?PackInfo.TempNum.tValue:0"
											:key="index">
											<view class="margin-tb-sm">
												<view
													style="display: flex; justify-content: space-around;align-items: center;flex-direction: column;width: 100%;height: 100%;padding: 5px;">
													<view class="text-bold text-blue2">
														{{PackInfo.Temp.tValue[item]}} ℃
													</view>
													<view class="text-sm">温度 {{item+1}}</view>
												</view>
											</view>
										</view>
									</view>
								</view>
							</view>
						</tn-collapse-item>
					</tn-collapse>
				</view>



				<view class="margin-sm radius-25" style="box-shadow: 2rpx 2rpx 4rpx 4rpx #def4f9;">
					<tn-collapse arrowColor='#0081ff'>
						<tn-collapse-item ref='collapse_2' icon="tn-icon-down-circle-simple" title="电压"
							subTitle='Voltage'>
							<view class="margin-sm grid col-2" style="min-height: 40px;">
								<template v-for="(item , index) in PackInfo.CellNum.tValue?PackInfo.CellNum.tValue:0"
									v-if="VCellInfo.items">
									<view :key="index" class="margin-tb-xs"
										style="display: flex; justify-content: space-around;">
										<view class="cu-capsule radius text-lg">
											<view class='cu-tag '
												:class="(VCellInfo.vMax===VCellInfo.items[item])?'bg-orange':(VCellInfo.vMin===VCellInfo.items[item]?'bg-green':'bg-blue')"
												style="width: 65px;">
												电芯{{(item+1)}}
											</view>
											<view class="cu-tag line-blue">
												{{VCellInfo.items[item]}} mV
											</view>
										</view>
									</view>

								</template>

							</view>
						</tn-collapse-item>
					</tn-collapse>
				</view>


				<view class="cu-list menu margin-sm bg-white radius-25"
					style="box-shadow: 2rpx 2rpx 4rpx 4rpx #def4f9;">
					<view class="cu-item padding-lr-sm" style="background: none;padding: 10px 10px 10px 20px;">
						<view class="content text-blue2">
							<view class="text-xl text-bold" style="letter-spacing: 1px;">应急充电</view>
							<view class="text-df text-black tn-padding-right-xs">此按钮为充电应急启动，启动过程中不要退出小程序。
							</view>
						</view>
						<view class="action">
							<button class="cu-btn  cuIcon bg-blue shadow" @click="showConfirm">
								<text class="tn-icon-power  tn-text-lg-xxl" style=""></text>
							</button>

							<!-- <tn-switch v-model="UVObj.val" :size="60" @change='toStartFun'></tn-switch> -->
						</view>
					</view>
				</view>

				<view style="height: 10vh;background: none;"></view>
			</view>
			<!-- 密码弹窗 -->
			<template v-if="showPassword">
				<tn-modal :value="showPassword" @click="e=>onDialogClick(e,'CHECK')" @cancel="onDialogClose" custom
					:button="buttons" padding='30rpx'>
					<view class="custom-modal-content">
						<tn-form :labelWidth="80" style="width: 100%;">
							<tn-form-item label="密码:" :borderBottom="false">
								<tn-input v-model="dialogInput" border></tn-input>
							</tn-form-item>
						</tn-form>
					</view>
				</tn-modal>
			</template>
		</view>





		<!-- 检测弹窗 -->
		<tn-landscape :show="showCheck" :mask="true">
			<view class="check margin-lg" style="width: 100px;height: 100px;">
				<view class="loader">
					<view class="circle loading1"></view>
					<view class="circle loading2"></view>
					<view class="circle loading3"></view>
					<view class="circle loading4"></view>
					<view class="circle loading5"></view>
					<view class="circle loading6"></view>
					<view class="circle loading7"></view>
					<view class="circle loading8"></view>
				</view>
			</view>
			<view
				style="width: 360px;margin-top: 10px; padding:10px;display: flex;flex-direction: column;align-items: center;">
				<view class="text-bold text-white padding-tb text-xxl">{{currentStep.text}}</view>
				<tn-line-progress style="width: 260px;" :height="80" :percent="currentStep.progress"
					:striped="true"></tn-line-progress>
			</view>
		</tn-landscape>

		<!-- 发送指令弹窗 -->
		<tn-landscape :show="showTip" :mask="true">
			<view class="margin-lg tip" style="width: 100px;height: 100px;">
				<view class="load">
					<text></text>
					<text></text>
					<text></text>
					<text></text>
				</view>
			</view>
			<view style="width: 360px;padding:10px;display: flex;flex-direction: column;align-items: center;">
				<view class="padding bg-white" style="text-align: center;" v-if="isMQTT===false">
					<view class="text-bold text-red  text-xxl ">请重新插拔电池充电器</view>
					<view class="text-bold text-red  text-xxl ">不要关闭小程序</view>
				</view>
				<view class="padding bg-white" style="text-align: center;" v-else>
					<view class="text-bold text-red  text-xxl ">远程参数指令下发中</view>
					<view class="text-bold text-red  text-xxl ">不要关闭小程序</view>
				</view>
			</view>
		</tn-landscape>
	</view>

</template>

<script>
	import {
		getDeviceAuthInfo
	} from '@/api/modules/common.js'
	import {
		getToken
	} from "@/common/storage/auth.js"

	import BLE from "@/libs/bluetooth/BLE.js";
	import Protocol from "@/libs/protocol/jiabaida/protocol.js";
	import bleData from "@/libs/protocol/jiabaida/bleData.js";
	import zuBattery from '../components/zu-battery/zu-battery'
	import car from '@/pages_ble/static/car.png'
	import san from '@/pages_ble/static/san.png'
	import san2 from '@/pages_ble/static/san2.png'
	import one from '@/pages_ble/static/2.jpg'
	import store from '@/store/index.js'

	const JiaBaiDaKey = 'JiaBD.UV'

	let _self;

	let timer = null
	let sendTimer = null
	let changingTimer = null
	export default {
		components: {
			zuBattery
		},
		data() {
			return {
				bleName: null,
				isMQTT: false,
				showCheck: true, //是否检查 低压
				isChecked: false, //是否检查 低压
				showTip: false, //更改参数提示
				dialogInput: '',
				resData: '',
				PowerW: 0,
				currentStepIndex: 0,
				currentStep: {},
				UVObj: {},
				userLevels: {},
				PackInfo: bleData.packInfo,
				VCellInfo: [],
				AllParams: {
					PackInfo: bleData.packInfo,
					Params1: bleData.Params1,
					Params2: bleData.Params2,
					Params3: bleData.Params3,
					Params4: bleData.Params4,
					Params6: bleData.Params6,
					Params7: bleData.Params7,
					Params8: bleData.Params8,
					Numbers: bleData.Numbers,
				},
				carImgs: [one, car, san, san2],
				showPasswordCount: 0,
				isWrite: false,
				isSendCmd: false,
				sendEnable: false,
				showPassword: false,
				readIndex: 0,
				SOCValue: 0,
				imgNum: 0,
				buttons: [{
						text: '取消',
						backgroundColor: '#AAAAAA',
						fontColor: '#FFFFFF'
					},
					{
						text: '确定',
						backgroundColor: '#01BEFF',
						fontColor: '#FFFFFF'
					}
				]
			}
		},
		onLoad(options) {
			_self = this
			// 保持屏幕常亮
			// #ifdef MP-WEIXIN
			uni.setKeepScreenOn({
				keepScreenOn: true
			});
			// #endif
			if (options.name) {
				this.bleName = options.name
			} else {
				this.bleName = getApp().globalData.bleObj.name
			}
			var that = this;
			that.isWrite = false;
			that.readIndex = 0;

			//设置值更改函数
			that.SetValueChanged();
			that.SetConnectionStateChange();

			that.updateProgress();

			// 获取用户等级密码信息
			// this.$api.common.listUserLevel().then(res => {
			// 	this.userLevels = {}
			// 	if (res.code === 200) {
			// 		for (var i = 0; i < res.data.length; i++) {
			// 			let t = res.data[i]
			// 			console.log(t);
			// 			this.userLevels['level.' + t.configKey.split('level.')[1]] = t.configValue
			// 		}
			// 		console.log('this.userLevels', this.userLevels);
			// 	}
			// })

		},
		onShow() {
			if (!getApp().globalData.bleObj.state) {
				// #ifdef MP-WEIXIN
				BLE.Connect(getApp().globalData.bleObj.deviceId, () => {})
				// #endif
			}
			let that = this
			if (sendTimer != null) {
				clearInterval(sendTimer)
				sendTimer = null;
			}
			if (timer != null) {
				clearInterval(timer)
				timer = null;
			}

			let version = store.state.vuex_ble_version
			let num = uni.getStorageSync("IMG_V" + version)
			if (num) {
				this.imgNum = num
			}


			this.isWrite = false
			this.isSendCmd = false
			that.sendFirstToBle()
			//定时读取蓝牙数据
			timer = setInterval(() => {
				that.sendFirstToBle()
				that.showPasswordCount = 0
			}, 2000)

			//定时发送数据到服务器
			sendTimer = setInterval(() => {
				that.sendDataToMqtt()
			}, 1000)

			const deviceId = that.bleName ? that.bleName : getApp().globalData.bleObj.name;
			if (deviceId) {
				// this.getMqttInfo(deviceId)
			}
			this.getMqttInfo(deviceId)
		},
		onHide() {
			if (sendTimer != null) {
				clearInterval(sendTimer)
				sendTimer = null;
			}
			if (timer != null) {
				clearInterval(timer)
				timer = null;
			}
			this.isWrite = false
			this.endMqtt()
		},
		onUnload() {
			if (sendTimer != null) {
				clearInterval(sendTimer)
				sendTimer = null;
			}
			if (timer != null) {
				clearInterval(timer)
				timer = null;
			}
			// if (getApp().globalData.bleObj.state) {
			// 	BLE.Close()
			// }
			this.endMqtt()
		},
		methods: {
			setImg() {
				_self.imgNum += 1
				if (_self.imgNum > 3) {
					_self.imgNum = 0
				}
				let version = store.state.vuex_ble_version
				uni.setStorageSync("IMG_V" + version, _self.imgNum)
			},
			mosBtnComfig(e, address) {
				_self.isSendCmd = true
				_self.isWrite = false
				let v = address + (e.target.value ? '00' : '01')
				this.$nextTick(() => {
					Protocol.writeToWrite('5A', 'FB', '02', v, async () => {
						_self.$tn.message.toast('指令下发成功')
						setTimeout(() => {
							_self.isSendCmd = false
						}, 1000)
					})
				})
			},
			showConfirm() {
				BLE.confirm('此按钮为充电应急启动，请确认插好充电器', () => {
					this.setUVRValue("Down")
				})
			},
			setUVRValue(val) {
				let that = this;
				const UV = that.AllParams.Params1['UV'].tValue * 1;
				const UVRVal = that.AllParams.Params1['UVR'].tValue * 1;
				if (val === 'UP') {
					console.log('开始检测');
					if ((UVRVal - 250) < UV) {
						console.log('释放电压小于正常值 加回去');
						let newUVR = UV + 300;
						_self.isSendCmd = true;
						let sendCMDStr = 'FA07001602' + UV.toString(16).toUpperCase().padStart(4, '0') + newUVR.toString(
							16).toUpperCase().padStart(4, '0')
						sendCMDStr = 'DD5A' + sendCMDStr + Protocol.checkCRC16(sendCMDStr) + '77'
						console.log('sendCMDStr: ', sendCMDStr);
						_self.$tn.message.toast('指令下发中')
						// 先进入工厂模式
						Protocol.writeStrToRead('DD5A00025678FF3077', async () => {
							setTimeout(() => {
								Protocol.writeStrToRead(sendCMDStr,
									async () => {
										setTimeout(() => {
											_self.$tn.message.toast('指令下发成功')
											_self.isSendCmd = false
											_self.isWrite = false
											Protocol.writeStrToRead(
												'DD5A01022828FFAD77',
												null);
										}, 2000)
									})
							}, 500)
						});
					}
					//判断 放电过流 保护值
					const DOCValue = (that.AllParams.Params1['DOC'].tValue * 1) / 1000
					if (DOCValue === 60 || DOCValue === 80) {
						let v = Math.round(65536 - ((that.AllParams.Params1['DOC'].tValue * 1 + 10000) / 10));
						let sendCMDStr = 'FA05001901' + v.toString(16).toUpperCase().padStart(4, '0');
						sendCMDStr = 'DD5A' + sendCMDStr + Protocol.checkCRC16(sendCMDStr) + '77'
						console.log('sendCMDStr: ', sendCMDStr);
						_self.$tn.message.toast('指令下发中')
						// 先进入工厂模式
						Protocol.writeStrToRead('DD5A00025678FF3077', async () => {
							setTimeout(() => {
								Protocol.writeStrToRead(sendCMDStr,
									async () => {
										setTimeout(() => {
											_self.$tn.message.toast('指令下发成功')
											_self.isSendCmd = false
											_self.isWrite = false
											Protocol.writeStrToRead(
												'DD5A01022828FFAD77',
												null);
										}, 2000)
									})
							}, 500)
						});
					}
					_self.isChecked = true;
				} else {
					_self.showTip = true;
					let newUVR = (UVRVal - 250);
					_self.isSendCmd = true;
					let sendCMDStr = 'FA07001602' + UV.toString(16).toUpperCase().padStart(4, '0') + newUVR.toString(16)
						.toUpperCase().padStart(4, '0');
					sendCMDStr = 'DD5A' + sendCMDStr + Protocol.checkCRC16(sendCMDStr) + '77';
					console.log('sendCMDStr: ', sendCMDStr);
					_self.$tn.message.toast("指令下发中")
					////先进入工厂模式
					Protocol.writeStrToRead('DD5A00025678FF3077', async () => {
						setTimeout(() => {
							Protocol.writeStrToRead(sendCMDStr,
								async () => {
									setTimeout(() => {
										_self.$tn.message.toast('指令下发成功')
										_self.isSendCmd = false
										_self.isWrite = false
										Protocol.writeStrToRead(
											'DD5A01022828FFAD77',
											null);
									}, 2000)
									setTimeout(() => {
										_self.setUVRValue("UP")
										_self.showTip = false;
									}, 12000)
								})
						}, 500)
					});
				}
			},
			/**
			 * 一键强启按钮
			 */
			toStartFun(val) {
				let that = this;
				if (!val) {
					//判断应急开关缓存
					let tempObj = uni.getStorageSync(JiaBaiDaKey);
					console.log('tempObj', tempObj);
					that.UVObj = {
						val: false
					}
					that.isSendCmd = true;
					let sendCMDStr = 'FA07001602' + tempObj['UV'].toString(16).toUpperCase().padStart(4, '0') + tempObj[
						'UVR'].toString(16).toUpperCase().padStart(4, '0')
					sendCMDStr = 'DD5A' + sendCMDStr + Protocol.checkCRC16(sendCMDStr) + '77'
					console.log('sendCMDStr: ', sendCMDStr);
					that.$tn.message.toast('指令下发中')
					//先进入工厂模式
					Protocol.writeStrToRead('DD5A00025678FF3077', async () => {
						setTimeout(() => {
							Protocol.writeStrToRead(sendCMDStr,
								async () => {
									setTimeout(() => {
										that.$tn.message.toast('指令下发成功')
										that.isSendCmd = false
										that.isWrite = false
										Protocol.writeStrToRead(
											'DD5A01022828FFAD77',
											() => {
												uni.removeStorageSync(JiaBaiDaKey);
											});
									}, 2000)
								})
						}, 500)
					});
				} else {
					BLE.confirm("此按钮为充电应急启动，充电正常后必须关闭按钮。", (res) => {
						const params = _self.AllParams.Params1;
						const UV = params['UV'].tValue;
						const UVR = params['UVR'].tValue;
						that.UVObj = {
							val: true,
							UV: UV,
							UVR: UVR
						}
						uni.setStorageSync(JiaBaiDaKey, that.UVObj);
						let sendCMDStr = 'DD5AFA070016020708076CFE6577'
						that.isSendCmd = true;
						that.$tn.message.toast('指令下发中')
						//先进入工厂模式
						Protocol.writeStrToRead('DD5A00025678FF3077', async () => {
							setTimeout(() => {
								Protocol.writeStrToRead(sendCMDStr,
									async () => {
										setTimeout(() => {
											that.$tn.message.toast('指令下发成功')
											that.isSendCmd = false
											that.isWrite = false
											Protocol.writeStrToRead(
												'DD5A01022828FFAD77',
												() => {});
										}, 2000)
									})
							}, 500)
						});
					})
				}

			},
			/**
			 * 连续点击标题或者 电池容量
			 * @param {Object} flag
			 */
			showPasswordFun(flag) {
				this.isSendCmd = true
				let count = this.showPasswordCount++
				if (count > 2 && flag === 'NAME') {
					//弹窗修改蓝牙名称
					this.showPassword = true
					this.dialogType = 'NAME'
				}
				if (count > 4 && flag === 'CONFIG') {
					//弹窗修改参数
					this.showPassword = true
					this.dialogType = 'CONFIG'
				}
			},
			/**
			 *
			 */
			onDialogClose() {
				this.showDialog = false;
				this.isSendCmd = false
				this.dialogInput = null
			},
			onDialogClick(e, type) {
				let that = this
				let input = that.dialogInput
				if (e.index < 1) {
					that.showPassword = false;
					that.showDialog = false;
					that.dialogInput = ''
					return
				}
				if (type === 'CHECK') {
					that.showPassword = false
					// 判断密码
					if (that.dialogType === 'NAME' && input === that.userLevels['level.1']) {
						that.showDialog = true
						that.dialogInput = ''
						return
					}
					if (that.dialogType === 'CONFIG' && input === that.userLevels['level.2']) {
						that.dialogInput = ''
						uni.navigateTo({
							url: '/pages_ble/ble/jiabaida/config?n=' + this.bleName
						})
					}
					that.showDialog = false

				}
			},
			/**
			 * 发送数据给MQTT
			 */
			sendDataToMqtt() {
				let that = this
				var state = getApp().globalData.bleObj.state;
				if (that.sendEnable && state) {
					let messages = []
					for (let key in that.AllParams) {
						let targetParams = that.AllParams[key]
						for (let paramKey in targetParams) {
							messages.push({
								id: paramKey,
								value: targetParams[paramKey].tValue,
								name: targetParams[paramKey].name,
								remark: ''
							})
						}
					}
					// 发送电压信息
					if (that.VCellInfo.items) {
						messages.push({
							id: 'vMax',
							value: that.VCellInfo.vMax,
							name: '最高电压',
							remark: ''
						})
						messages.push({
							id: 'vMin',
							value: that.VCellInfo.vMin,
							name: '最低电压',
							remark: ''
						})
						messages.push({
							id: 'vItems',
							value: that.VCellInfo.items,
							name: '电芯电压',
							remark: ''
						})
					}

					console.log('sendDataToMqtt', messages);
					that.$mqttTool.publish(
						`/${that.deviceInfo.productId}/${that.deviceInfo.serialNumber}/property/post`,
						JSON.stringify(messages), 'name')
				}
			},
			sendFirstToBle() {
				let that = this
				var state = getApp().globalData.bleObj.state;
				var deviceId = getApp().globalData.bleObj.deviceId;
				var isWrite = that.isWrite;
				if (state && deviceId != '' && isWrite === false && _self.isSendCmd === false) {
					that.readIndex = 0;
					that.isWrite = true;
					Protocol.writeStrToRead(CMDs[that.readIndex].cmd, function(res) {
						console.log('sendFirstToBle', res);
						setTimeout(() => {
							that.$refs['collapse_1'].init()
							that.$refs['collapse_2'].init()
							that.$forceUpdate()
						}, 2000)
					});
				} else {

					console.log('timer');
				}
			},
			SetConnectionStateChange() {
				BLE.bleCallBack.ConnectionStateChange = () => {
					if (!getApp().globalData.bleObj.state) {
						BLE.Connect(getApp().globalData.bleObj.deviceId, () => {
							_self.isWrite = false
							_self.isSendCmd = false
							_self.sendFirstToBle()
						})
					}
				}
			},
			//设置蓝牙请求数据
			SetValueChanged() {
				var that = this;
				_self = this
				//处理数据
				BLE.bleCallBack.CharacteristicValueChange = async function(res) {
					if (_self.isSendCmd) {
						console.log('蓝牙返回数据', res);
						console.log('发送指令成功');
						return
					}
					var current = CMDs[that.readIndex];
					let lastBit = res.substr(res.length - 2, res.length - 1)
					_self.resData += res
					if (lastBit === '77') {
						let CRC = _self.resData.substr(_self.resData.length - 6, 4)
						if (CRC === Protocol.checkCRC16(_self.resData.substr(4, _self.resData.length - 10))) {
							let packages = Protocol.solutionData(_self.resData)
							let data = packages.data
							if (current.name === 'PACK') {
								//console.log('PACK', _self.resData);
								for (let itemKey in _self.PackInfo) {
									let item = _self.PackInfo[itemKey]
									if ('Temp' === item.name) {
										let num = _self.PackInfo['TempNum'].tValue
										let str = data.substr(0, num * 2 * 2)
										item.tValue = []
										for (var i = 0; i < num; i++) {
											let tStr = str.substr(i * 4, (i + 1) * 4)
											item.tValue.push(((parseInt('0x' + tStr) - 2731) * 0.1).toFixed(1))
										}
										data = data.substr(str.length, data.length)
									} else {
										item.value = '0x' + data.substr(0, item.len * 2)
										item.tValue = parseInt(item.value) * item.gain
										if ('CurCadc' === item.name) {
											var v = new Int16Array([parseInt(item.value, 16)])[0];
											item.tValue = (v * item.gain);

											//判断是否点击了 应急充电按钮
											if (_self.showTip && item.tValue > 0) {
												_self.setUVRValue("UP")
												_self.showTip = false;
											}

										}
										if (item.gain < 1) {
											item.tValue = item.tValue.toFixed(2)
										}
										//判断mos
										if (item.name === 'MosCtrl') {
											var v = parseInt(item.value).toString(2);
											item.tValue = v.split('').reverse();
										}

										if (item.name === 'Protect') {}

										data = data.substr(item.len * 2, data.length)
									}
								}
								//设置功率
								_self.PowerW = (_self.PackInfo['Voltage'].tValue * _self.PackInfo['CurCadc']
									.tValue).toFixed(2)
							}
							if (current.name === 'VCell') {
								_self.VCellInfo = {
									vMax: 0,
									vMin: 0,
									items: []
								}
								const CellNum = _self.PackInfo.CellNum.tValue
								for (var i = 0; i < CellNum; i++) {
									let value = parseInt('0x' + data.substr(i * 4, 4))
									if (i < 1) {
										_self.VCellInfo['vMax'] = value
										_self.VCellInfo['vMin'] = value
									}
									if (_self.VCellInfo['vMax'] < value) {
										_self.VCellInfo['vMax'] = value
									}
									if (_self.VCellInfo['vMin'] > value) {
										_self.VCellInfo['vMin'] = value
									}
									_self.VCellInfo.items.push(value)
								}
							}
							if (current.name === 'Numbers') {
								let numbers = _self.AllParams.Numbers
								let items = readNumbers(data);
								for (var i = 0; i < numbers.length; i++) {
									numbers[i].tValue = items[i]
								}
								_self.AllParams.Numbers = numbers
							}

							if (current.name === 'Params1') {
								SetTargetVal(_self.AllParams.Params1, data)
								let UV = _self.AllParams.Params1['UV'].tValue * 1;
								let UVR = _self.AllParams.Params1['UVR'].tValue * 1;
								if (!_self.isChecked) {
									that.setUVRValue('UP')
								}

								//判断 充电过流保护  放电过流保护值
								//console.log('充电过流保护', _self.AllParams.Params1['COC'].tValue);
								//onsole.log('放电过流保护值', _self.AllParams.Params1['DOC'].tValue);

							}

							if (current.name === 'Params2') {
								_self.AllParams.Params2.Out_F.tValue = hexToAscii(data.substr(8, parseInt(data
									.substr(6, 2)) * 2))
							}
							if (current.name === 'Params3') {
								_self.AllParams.Params3.BMS_CODE.tValue = hexToAscii(data.substr(8, parseInt(data
									.substr(6, 2)) * 2))

							}
							if (current.name === 'Params4') {
								_self.AllParams.Params4.Bar_CODE.tValue = hexToAscii(data.substr(8, parseInt(data
									.substr(6, 2)) * 2))

							}
							if (current.name === 'Params6') {
								_self.AllParams.Params6.BATTERY.tValue = hexToAscii(data.substr(8, parseInt(data
									.substr(6, 2)) * 2))
							}

							if (current.name === 'Params7') {
								_self.AllParams.Params7.ID_CODE.tValue = hexToAscii(data.substr(8, parseInt(data
									.substr(6, 2)) * 2))

							}

							if (current.name === 'Params8') {
								let len = _self.resData.substr(14, 2)
								let size = parseInt('0x' + len) - 1
								let hex = _self.resData.substr(16, size)
								_self.AllParams.Params8.BMS_NAME.tValue = hexToAscii(hex)
								//console.log('硬件名称: ', hexToAscii(hex));
							}
							if (current.name.indexOf("Params") > -1) {
								// console.log('current.cmd', current.cmd);
								//console.log('蓝牙返回数据', _self.resData);
							}
						}
						_self.resData = '';
						that.readIndex++;
						if (that.readIndex >= CMDs.length) {
							//console.log('_self.AllParams', _self.AllParams);
							that.readIndex = 0;
						}
						Protocol.writeStrToRead(CMDs[that.readIndex].cmd, function(res) {});
					}
				}
			},
			/**
			 * 获取MQTT连接信息
			 */
			getMqttInfo(deviceId) {
				let that = this;
				let productCode = getApp().globalData.bleVersion
				// that.$api.device.getMqttInfo(deviceId, productCode).then(res => {
				// 	if (!res.data || !res.data.device) {
				// 		return
				// 	}
				// 	let device = res.data.device
				// 	let mqttInfo = res.data.mqttInfo
				// 	let info = {
				// 		clientId: mqttInfo.clientId,
				// 		username: mqttInfo.username,
				// 		password: mqttInfo.passwd,
				// 	}
				// 	setTimeout(async () => {
				// 		await this.connectMqtt(info)
				// 		this.mqttSubscribe(device);
				// 		this.deviceInfo = device;
				// 		this.mqttCallback();
				// 	}, 100)
				// })


				// getDeviceAuthInfo('V--03').then(res => {
				// 	const info = res.data
				// 	let one = '/sys/' + info.username.split('&')[1] + '/' + info.username.split('&')[0] + '/#'
				// 	let topics = [one]
				// 	setTimeout(async () => {
				// 		await this.connectMqtt(info)
				// 		that.$mqttTool.subscribe(topics);
				// 		this.mqttCallback();
				// 	}, 1000)

				// })

			},
			async mqttSendOk(messages) {
				let that = this
				that.$mqttTool.publish(
					`/${that.deviceInfo.productId}/${that.deviceInfo.serialNumber}/property/post`,
					JSON.stringify(messages), '')
			},
			/* 断开Mqtt消息服务器 */
			async endMqtt() {
				await this.$mqttTool.end();
				this.sendEnable = false
			},
			/* 连接Mqtt消息服务器 */
			async connectMqtt(info) {
				let that = this
				if (this.$mqttTool.client === null) {
					if (info && info.username) {
						await _self.$mqttTool.connect(info);
						_self.$mqttTool.client.on('connect', function(res) {
							console.log("连接Mqtt消息服务器");
						});
					}
				}
			},
			/* Mqtt回调处理  */
			mqttCallback() {
				let that = this
				let topicArrs = [
					'/function/get',
					'/monitor/get'
				]
				this.$mqttTool.client.on('message', async (topic, message, buffer) => {
					console.log('message:', message.toString());
					console.log('topic:', topic);
					message = JSON.parse(message.toString());
					if (!message) {
						return;
					};
					if (topic.includes(topicArrs[1])) {
						if (message.count * 1 > 0) {
							that.sendEnable = true
							setTimeout(() => {
								that.sendEnable = false
							}, message.count * 1000)
						} else {
							that.sendEnable = false
						}
						let MAC = getApp().globalData.bleObj.MAC
						// utils.readListWithFilterExpire(MAC + "PROTECT").then(saveArr => {
						// 	console.log('saveArr', saveArr);
						// 	// 发送后台
						// 	for (var i = 0; i < saveArr.length; i++) {
						// 		let t = saveArr[i];
						// 		t['productId'] = productId
						// 		t['alertLevel'] = 3
						// 		t['status'] = 1
						// 		t['detail'] = ''
						// 		saveAlertLog(t).then(res => {
						// 			console.log('上传成功', res);
						// 		})
						// 	}
						// })
					}

					if (topic.includes(topicArrs[0])) {
						for (var i = 0; i < message.length; i++) {
							let item = message[i]
							console.log(item);
							let address = null;
							for (let key in Object.keys(_self.AllParams)) {
								let keyStr = Object.keys(_self.AllParams)[key]
								if (keyStr.indexOf("Params") > -1) {
									let params = _self.AllParams[keyStr];
									for (let pKey in params) {
										if (pKey === item.id) {
											address = params[pKey].address
											break;
										}
									}
								}
							}
							let v = parseFloat(item.value);
							if (!isNaN(v) && address) {
								that.setBleVal(address, item)
							} else {
								console.log('获取address失败');
							}
						}
					}
				});
			},
			/** Mqtt订阅主题 */
			mqttSubscribe(device) {
				// 订阅当前设备状态和实时监测
				let topics = buildTopics(device);
				this.$mqttTool.subscribe(topics);
			},
			setBleVal(address, item) {
				let that = this
				let v = parseFloat(item.value);
				that.isSendCmd = true;
				that.isMQTT = true;
				that.showTip = true;
				//先进入工厂模式
				Protocol.writeStrToRead('DD5A00025678FF3077', async () => {
					let valHex = Protocol.encryption(address, v)
					setTimeout(() => {
						Protocol.writeToWrite('5A', 'FA', '05', (address * 1).toString(16)
							.toUpperCase().padStart(4, '0') + '01' + valHex,
							async () => {
								setTimeout(() => {
									that.isSendCmd = false;
									that.isWrite = false;
									that.isMQTT = false;
									that.showTip = false;
									that.$tn.message.toast('指令下发成功')
									Protocol.writeStrToRead(
										'DD5A01022828FFAD77',
										() => {
											that.mqttSendOk([item])
										});
								}, 2500)
							})
					}, 500)
				});
			},
			updateProgress() {
				if (this.currentStepIndex < steps.length) {
					this.currentStep = steps[this.currentStepIndex]
					this.currentStepIndex++;
					// 模拟异步操作，每1秒更新一次进度
					setTimeout(this.updateProgress, 1000);
				} else {
					this.showCheck = false;
				}
			}
		}
	}

	/**
	 * MQTT主题订阅配置
	 * @param {Object} device 设备信息
	 */
	function buildTopics(device) {
		let topics = [];
		let preUrl = '/' + device.productId + '/' + device.serialNumber;
		// 订阅当前设备状态和实时监测
		let functionGet = preUrl + '/function/get';
		let topicInfo = preUrl + '/info/get';
		let topicMonitor = preUrl + '/monitor/get';
		topics.push(functionGet);
		topics.push(topicInfo);
		topics.push(topicMonitor);
		return topics
	}

	function hexToAscii(hexStr) {
		let asciiStr = '';
		for (let i = 0; i < hexStr.length; i += 2) {
			const byte = hexStr.substr(i, 2);
			const charCode = parseInt(byte, 16);
			if (charCode < 0x20 || charCode > 0x7E) {
				// 控制字符或非 ASCII 字符，显示为 \xHH
				asciiStr += ``;
			} else {
				// 可打印 ASCII 字符
				asciiStr += String.fromCharCode(charCode);
			}
		}
		return asciiStr;
	}

	function SetTargetVal(targetObj, valStr) {
		valStr = valStr.substr(6, valStr.length - 1)
		let targetKeys = Object.keys(targetObj)
		for (var i = 0; i < targetKeys.length; i++) {
			let key = targetKeys[i]
			let target = targetObj[key]
			target.value = valStr.substr(i * 2 * target.len, 2 * target.len);
			let num = Protocol.algorithm(target.address, target.value)
			const n = parseFloat(num);
			const tValue = isNaN(n) ? num : n % 1 === 0 ? n : parseFloat(n.toFixed(1));
			if (key === 'CreateDate') {
				target.tValue = parseDateFromHex('0x' + target.value)
			} else if (key === 'DOC') {
				var v = parseInt("0x" + target.value);
				target.tValue = parseFloat(((65536 - v) * 10).toFixed(1));
			} else {
				target.tValue = tValue;
			}
			targetObj[key] = target
		}
	}


	function parseDateFromHex(hexValue) {
		// 提取日期
		let date = hexValue & 0x1f; // 最低5位表示日期

		// 提取月份
		let month = (hexValue >> 5) & 0x0f; // 第6到第9位表示月份

		// 提取年份
		let year = ((hexValue >> 9) & 0x3f) + 2000; // 最高6位表示年份，加上2000得到实际年份

		return `${year}年${month}月${date}日`;
	}

	function readNumbers(hexString) {
		// 将十六进制字符串转换为字节数组
		const bytes = [];
		for (let i = 0; i < hexString.length; i += 2) {
			bytes.push(parseInt(hexString.substr(i, 2), 16));
		}
		// 解析每个 2BYTE 数据项
		function parseTwoBytes(highByte, lowByte) {
			return (highByte << 8) | lowByte;
		}
		const dataItems = [];
		for (let i = 0; i < bytes.length; i += 2) {
			const highByte = bytes[i];
			const lowByte = bytes[i + 1];
			dataItems.push(parseTwoBytes(highByte, lowByte));
		}
		return dataItems;
	}



	const CMDs = [{
		name: 'PACK',
		cmd: 'DDA50300FFFD77'
	}, {
		name: 'VCell',
		cmd: 'DDA50400FFFC77'
	}, {
		name: 'Version',
		cmd: 'DDA50500FFFB77'
	}, {
		name: 'Numbers', //保护统计次数
		cmd: 'DDA5AA00FF5677'
	}, {
		name: 'Params1',
		cmd: 'DDA5FA03000037FECC77'
	}, {
		name: 'Params2', //生产厂商信息
		cmd: 'DDA5FA03003810FEBB77'
	}, {
		name: 'Params3', //BMS-编码信息
		cmd: 'DDA5FA03004810FEAB77'
	}, {
		name: 'Params4', //条形码信息
		cmd: 'DDA5FA03005810FE9B77'
	}, {
		name: 'Params5',
		cmd: 'DDA5FA03006813FE8877'
	}, {
		name: 'Params6', //电池型号
		cmd: 'DDA5FA03009E0CFE5977'
	}, {
		name: 'Params7', //唯一 ID 码
		cmd: 'DDA5FA0300AA06FE5377'
	}, {
		name: 'Params8', //硬件名称
		cmd: 'DDA5FA0300B004FE4F77'
	}, ]

	const steps = [{
			progress: 10,
			text: "正在扫描电池..."
		},
		{
			progress: 30,
			text: "检查电池电压..."
		},
		{
			progress: 50,
			text: "检查电池电流..."
		},
		{
			progress: 80,
			text: "评估电池健康状态..."
		},
		{
			progress: 100,
			text: "电池检测完成"
		}
	];
</script>

<style lang="scss" scoped>
	.bg-white {
		background-color: rgb(255 255 255 / 60%);
	}


	.warp {
		color: #404e75;
		min-height: 100vh;
		background-size: cover;
		background-attachment: fixed;
	}

	.container {
		overflow: auto;
		height: 100vh;
		width: 100%;
		position: absolute;
		background-color: rgb(255 255 255 / 0%);
		top: 0%;
		left: 0%;
	}

	.b-card {
		background-color: #FFFFFF;
		border-radius: 18rpx;
		box-shadow: 2rpx 2rpx 4rpx 4rpx #def4f9;
	}
</style>


<style lang="scss" scoped>
	.radius-25 {
		border-radius: 15rpx;
	}

	.PhotographerBoxL {
		width: 35%;
		text-align: center;
		float: left;
	}

	.bg-img-dc-max {
		background-image: url('/static/img/ble/dx-max.png');
		background-size: 100% 100%;
		color: #13227a;
		height: 90rpx;
		width: 86px;
	}

	.bg-img-dc-min {
		background-image: url('/static/img/ble/dx-min.png');
		background-size: 100% 100%;
		height: 90rpx;
		color: #0b988f;
		width: 86px;
	}

	.bg-img-dc {
		background-image: url('/static/img/ble/dx.png');
		background-size: 100% 100%;
		height: 90rpx;
		width: 86px;
		color: #1296db;
	}

	.check {

		/* 加载动画*/
		.loader {
			position: absolute;
			width: 120rpx;
			height: 120rpx;
			top: 25%;
			left: 50%;
			transform: translate(-50%, -50%);
		}

		.circle {
			color: #01BEFF;
			position: absolute;
			border-radius: 100%;
			width: 30rpx;
			height: 30rpx;
			display: inline-block;
			float: none;
			background-color: currentColor;
			border: 0 solid currentColor;
			-webkit-animation: spin 1s infinite ease-in-out;
			-moz-animation: spin 1s infinite ease-in-out;
			-o-animation: spin 1s infinite ease-in-out;
			animation: spin 1s infinite ease-in-out
		}

		.loader :nth-child(1) {
			top: 5%;
			left: 50%;
			-webkit-animation-delay: -.875s;
			-moz-animation-delay: -.875s;
			-o-animation-delay: -.875s;
			animation-delay: -.875s
		}

		.loader :nth-child(2) {
			top: 18.1801948466%;
			left: 81.8198051534%;
			-webkit-animation-delay: -.75s;
			-moz-animation-delay: -.75s;
			-o-animation-delay: -.75s;
			animation-delay: -.75s
		}

		.loader :nth-child(3) {
			top: 50%;
			left: 95%;
			-webkit-animation-delay: -.625s;
			-moz-animation-delay: -.625s;
			-o-animation-delay: -.625s;
			animation-delay: -.625s
		}

		.loader :nth-child(4) {
			top: 81.8198051534%;
			left: 81.8198051534%;
			-webkit-animation-delay: -.5s;
			-moz-animation-delay: -.5s;
			-o-animation-delay: -.5s;
			animation-delay: -.5s
		}

		.loader :nth-child(5) {
			top: 94.9999999966%;
			left: 50.0000000005%;
			-webkit-animation-delay: -.375s;
			-moz-animation-delay: -.375s;
			-o-animation-delay: -.375s;
			animation-delay: -.375s
		}

		.loader :nth-child(6) {
			top: 81.8198046966%;
			left: 18.1801949248%;
			-webkit-animation-delay: -.25s;
			-moz-animation-delay: -.25s;
			-o-animation-delay: -.25s;
			animation-delay: -.25s
		}

		.loader :nth-child(7) {
			top: 49.9999750815%;
			left: 5.0000051215%;
			-webkit-animation-delay: -.125s;
			-moz-animation-delay: -.125s;
			-o-animation-delay: -.125s;
			animation-delay: -.125s
		}

		.loader :nth-child(8) {
			top: 18.179464974%;
			left: 18.1803700518%;
			-webkit-animation-delay: 0s;
			-moz-animation-delay: 0s;
			-o-animation-delay: 0s;
			animation-delay: 0s
		}

		@-webkit-keyframes spin {

			0%,
			100% {
				opacity: 1;
				-webkit-transform: scale(1);
				transform: scale(1)
			}

			20% {
				opacity: 1
			}

			80% {
				opacity: 0;
				-webkit-transform: scale(0);
				transform: scale(0)
			}
		}

		@-moz-keyframes spin {

			0%,
			100% {
				opacity: 1;
				-moz-transform: scale(1);
				transform: scale(1)
			}

			20% {
				opacity: 1
			}

			80% {
				opacity: 0;
				-moz-transform: scale(0);
				transform: scale(0)
			}
		}

		@-o-keyframes spin {

			0%,
			100% {
				opacity: 1;
				-o-transform: scale(1);
				transform: scale(1)
			}

			20% {
				opacity: 1
			}

			80% {
				opacity: 0;
				-o-transform: scale(0);
				transform: scale(0)
			}
		}

		@keyframes spin {

			0%,
			100% {
				opacity: 1;
				-webkit-transform: scale(1);
				-moz-transform: scale(1);
				-o-transform: scale(1);
				transform: scale(1)
			}

			20% {
				opacity: 1
			}

			80% {
				opacity: 0;
				-webkit-transform: scale(0);
				-moz-transform: scale(0);
				-o-transform: scale(0);
				transform: scale(0)
			}
		}

	}

	.tip {

		/* 加载 */
		.load {
			position: absolute;
			top: 40%;
			left: 50%;
			transform: translate(-50%, -50%);
			width: 60px;
			height: 60px;
		}

		.load text {
			border: 0;
			margin: 0;
			width: 40%;
			height: 40%;
			position: absolute;
			border-radius: 50%;
			animation: spinTip 2s ease infinite
		}

		.load :first-child {
			background: #4B98FE;
			animation-delay: -1.5s
		}

		.load :nth-child(2) {
			background: #00D05E;
			animation-delay: -1s
		}

		.load :nth-child(3) {
			background: #FFAC00;
			animation-delay: -0.5s
		}

		.load :last-child {
			background: #FB6A67
		}


		@keyframes spinTip {

			0%,
			100% {
				transform: translate(0)
			}

			25% {
				transform: translate(160%)
			}

			50% {
				transform: translate(160%, 160%)
			}

			75% {
				transform: translate(0, 160%)
			}
		}
	}
</style>